package com.deercrowing.takeaway.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.deercrowing.takeaway.common.constant.MessageConstant;
import com.deercrowing.takeaway.common.constant.OrderStatusConstant;
import com.deercrowing.takeaway.common.constant.PayStatusConstant;
import com.deercrowing.takeaway.common.exception.BusinessException;
import com.deercrowing.takeaway.common.util.OrderIDGenerator;
import com.deercrowing.takeaway.common.util.OrderNumberGenerator;
import com.deercrowing.takeaway.common.util.WeChatPayUtil;
import com.deercrowing.takeaway.context.BaseContext;
import com.deercrowing.takeaway.dao.*;
import com.deercrowing.takeaway.entity.*;
import com.deercrowing.takeaway.service.OrdersService;
import com.deercrowing.takeaway.vo.OrderPaymentVO;
import com.deercrowing.takeaway.vo.OrdersPageVO;
import com.deercrowing.takeaway.vo.OrdersStatusNumberVO;
import com.deercrowing.takeaway.vo.OrdersVO;
import com.deercrowing.takeaway.websocket.WebSocketServer;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 订单表(Orders)表服务实现类
 *
 * @author guoyongxiang
 * @since 2024-07-11 16:04:43
 */
@Service
@Slf4j
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, OrdersEntity> implements OrdersService {

    @Autowired
    OrdersMapper ordersMapper;

    @Autowired
    UsersMapper usersMapper;

    @Autowired
    AddressMapper addressMapper;

    @Autowired
    ShoppingCartMapper shoppingCartMapper;

    @Autowired
    OrderDetailMapper orderDetailMapper;

    @Autowired
    WeChatPayUtil weChatPayUtil;

    @Autowired
    WebSocketServer webSocketServer;


    @Override
    public IPage<OrdersVO> searchByCondition(OrdersPageVO ordersPageVO) {
        int page = ordersPageVO.getPage() == null ? 1 : ordersPageVO.getPage();
        int pageSize = ordersPageVO.getPageSize() == null ? 10 : ordersPageVO.getPageSize();

        Integer limit = (page - 1) * pageSize;
        ordersPageVO.setPage(limit);
        ordersPageVO.setPageSize(pageSize);

        List<OrdersEntity> ordersEntityList = ordersMapper.selectListByCondition(ordersPageVO);

        if (ordersEntityList.size() < 0){
            throw new BusinessException(MessageConstant.ORDER_NOT_FOUND);
        }

        List<OrdersVO> ordersVOList = ordersEntityList.stream()
                .map(source -> new OrdersVO(
                        source.getId(),
                        source.getNumber(),
                        source.getStatus(),
                        null,
                        source.getOrderTime(),
                        source.getCheckoutTime(),
                        source.getPayMethod(),
                        source.getAmount(),
                        source.getRemark(),
                        source.getPhone(),
                        source.getAddressId(),
                        source.getAddress(),
                        source.getConsignee(),
                        source.getCancelReason(),
                        source.getRejectionReason(),
                        source.getCancelTime(),
                        source.getEstimatedDeliveryTime(),
                        source.getDeliveryTime(),
                        source.getPackAmount(),
                        source.getTablewareNumber(),
                        null))
                .collect(Collectors.toList());

        Integer count = ordersMapper.countOrderNum(ordersPageVO);

        IPage<OrdersVO> entityIPage = new Page<>(page, pageSize);
        entityIPage.setRecords(ordersVOList);
        entityIPage.setTotal(count);

        return entityIPage;
    }

    @Override
    public OrdersStatusNumberVO searchByStatus() {
        OrdersStatusNumberVO ordersStatusNumberVO = ordersMapper.selectByStatusNumber();
        return ordersStatusNumberVO;
    }

    @Override
    public void ordersByConfirm(OrdersVO ordersVO) {
        OrdersEntity ordersEntity = ordersMapper.selectById(ordersVO.getId());
        if (ObjectUtils.isEmpty(ordersEntity)){
            throw new NullPointerException();
        }

        ordersMapper.updateByConfirm(ordersVO);
    }

    @Override
    public OrdersVO searchById(Long id) {
        OrdersEntity ordersEntity = ordersMapper.selectById(id);
        if (ObjectUtils.isEmpty(ordersEntity)){
            throw new BusinessException(MessageConstant.ORDER_NOT_FOUND);
        }

        OrdersVO ordersVO = new OrdersVO();
        BeanUtils.copyProperties(ordersEntity,ordersVO);

        List<OrderDetailEntity> orderDetailEntityList = orderDetailMapper.selectListByOrderId(id);
        ordersVO.setOrderDetailEntityList(orderDetailEntityList);
        return ordersVO;
    }

    @Override
    public void ordersByCancel(OrdersVO ordersVO) throws Exception {
        OrdersEntity ordersEntity = ordersMapper.selectById(ordersVO.getId());
        if (ObjectUtils.isEmpty(ordersEntity)){
            throw new BusinessException(MessageConstant.ORDER_NOT_FOUND);
        }

        if (ordersEntity.getPayStatus() == 1){
            //用户已支付，需要退款
            /*String refund = weChatPayUtil.refund(
                    ordersEntity.getNumber(),
                    ordersEntity.getNumber(),
                    new BigDecimal(0.01),
                    new BigDecimal(0.01));
            log.info("申请退款：{}", refund);*/
        }

        ordersEntity.setCancelTime(LocalDateTime.now())
                    .setStatus(OrderStatusConstant.CANCEL)
                    .setCancelReason(ordersVO.getCancelReason())
                    .updateById();
    }

    @Override
    public void ordersByRejection(OrdersVO ordersVO) {
        OrdersEntity ordersEntity = ordersMapper.selectById(ordersVO.getId());
        if (ObjectUtils.isEmpty(ordersEntity)){
            throw new BusinessException(MessageConstant.ORDER_NOT_FOUND);
        }

        if (ordersEntity.getPayStatus() == 1){
            //用户已支付，需要退款
            /*String refund = weChatPayUtil.refund(
                    ordersEntity.getNumber(),
                    ordersEntity.getNumber(),
                    new BigDecimal(0.01),
                    new BigDecimal(0.01));
            log.info("申请退款：{}", refund);*/
        }

        ordersEntity.setCancelTime(LocalDateTime.now())
                    .setRejectionReason(ordersVO.getRejectionReason())
                    .setStatus(OrderStatusConstant.REFUND)
                    .updateById();
    }

    @Override
    public void ordersByComplete(Long id, Short status) {
        OrdersEntity ordersEntity = ordersMapper.selectById(id);
        if (ObjectUtils.isEmpty(ordersEntity)){
            throw new BusinessException(MessageConstant.ORDER_NOT_FOUND);
        }

        if (ordersEntity == null || !ordersEntity.getStatus().equals(OrderStatusConstant.DELIVERY_IN_PROGRESS)){
            throw new BusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }

        ordersEntity.setStatus(OrderStatusConstant.COMPLETED)
                    .setDeliveryTime(LocalDateTime.now())
                    .updateById();
    }

    @Override
    public void ordersByDelivery(Long id, Short status) {
        OrdersEntity ordersEntity = ordersMapper.selectById(id);
        if (ObjectUtils.isEmpty(ordersEntity)){
            throw new NullPointerException();
        }

        if (ordersEntity == null || !ordersEntity.getStatus().equals(OrderStatusConstant.RECEIVED_ORDER)){
            throw new BusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }

        ordersEntity.setStatus(OrderStatusConstant.DELIVERY_IN_PROGRESS)
                    .updateById();
    }

    @Override
    public IPage<OrdersVO> userOfHistoryOrders(OrdersPageVO ordersPageVO) {
        ordersPageVO.setUserId(BaseContext.getCurrentId());
        List<OrdersEntity> ordersEntityList = ordersMapper.selectListByUserId(ordersPageVO);
        if (ordersEntityList == null || ordersEntityList.size() < 0){
            throw new NullPointerException();
        }

        List<OrdersVO> ordersVOList = new ArrayList<>();

        for (OrdersEntity ordersEntity : ordersEntityList) {
            List<OrderDetailEntity> orderDetailEntityList = orderDetailMapper.selectListByOrderId(ordersEntity.getId());

            OrdersVO ordersVO = new OrdersVO();
            BeanUtils.copyProperties(ordersEntity,ordersVO);
            ordersVO.setOrderDetailEntityList(orderDetailEntityList);
            ordersVOList.add(ordersVO);
        }


        Integer page = ordersPageVO.getPage() == null ? 1 : ordersPageVO.getPage();
        Integer pageSize = ordersPageVO.getPageSize() == null ? 10 : ordersPageVO.getPageSize();

        IPage<OrdersVO> entityPage = new Page<>(page,pageSize,ordersVOList.size());
        entityPage.setRecords(ordersVOList);

        return entityPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrdersVO orderSubmit(OrdersVO ordersVO) {
        // 1、判断当前用户是否有地址
        AddressEntity addressEntity = addressMapper.selectById(ordersVO.getAddressId());
        if (ObjectUtils.isEmpty(addressEntity) || addressEntity == null){
            throw new BusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }

        // 2、判断当前用户购物车是否有数据
        ShoppingCartEntity shoppingCartEntity = new ShoppingCartEntity();
        shoppingCartEntity.setUserId(ordersVO.getUserId());
        List<ShoppingCartEntity> shoppingCartEntityList = shoppingCartMapper.selectByCondition(shoppingCartEntity);
        if (ObjectUtils.isEmpty(shoppingCartEntityList) || shoppingCartEntityList == null){
            throw new BusinessException(MessageConstant.SHOPPING_CART_IS_NULL);
        }


        // 3、补充字段
        OrderNumberGenerator orderNumberGenerator = new OrderNumberGenerator();
        OrdersEntity ordersEntity = new OrdersEntity();
        BeanUtils.copyProperties(ordersVO,ordersEntity);

        OrderIDGenerator orderIDGenerator = new OrderIDGenerator();
        Integer id = Integer.parseInt(orderIDGenerator.generateID());
        ordersEntity.setId(id.longValue())
                    .setNumber(orderNumberGenerator.generateID())
                    .setUserId(BaseContext.getCurrentId())
                    .setOrderTime(LocalDateTime.now())
                    .setPayStatus(PayStatusConstant.UN_PAID.shortValue())
                    .setStatus(OrderStatusConstant.NON_PAYMENT)
                    .setPhone(addressEntity.getPhone())
                    .setConsignee(addressEntity.getConsignee())
                    .setAddress(addressEntity.getDetail())
                    .insert();

        // 4、插入订单详情表
        for (ShoppingCartEntity shoppingCart : shoppingCartEntityList){
            OrderDetailEntity orderDetailEntity = new OrderDetailEntity();
            BeanUtils.copyProperties(shoppingCart,orderDetailEntity);
            orderDetailEntity.setId(System.currentTimeMillis())
                    .setOrderId(id.longValue());
            orderDetailMapper.insert(orderDetailEntity);
        }

        // 5、清空购物车数据
        shoppingCartMapper.deleteByUserId(BaseContext.getCurrentId());

        OrdersEntity entity = ordersMapper.selectById(id);
        BeanUtils.copyProperties(entity,ordersVO);

        return ordersVO;
    }

    @Override
    public OrderPaymentVO orderPayment(String orderNumber) throws Exception {
        // 当前登录用户id
        Long userId = BaseContext.getCurrentId();
        UsersEntity usersEntity = usersMapper.selectById(userId);

        /*//调用微信支付接口，生成预支付交易单
        JSONObject jsonObject = weChatPayUtil.pay(
                orderNumber, //商户订单号
                new BigDecimal(0.01), //支付金额，单位 元
                "外卖订单", //商品描述
                usersEntity.getOpenid() //微信用户的openid
        );*/
        JSONObject jsonObject = new JSONObject();

        if (jsonObject.getString("code") != null && jsonObject.getString("code").equals("ORDERPAID")) {
            throw new BusinessException("该订单已支付");
        }

        OrderPaymentVO orderPaymentVO = jsonObject.toJavaObject(OrderPaymentVO.class);
        orderPaymentVO.setPackageStr(jsonObject.getString("package"));

        return orderPaymentVO;
    }

    @Override
    public void paySuccess(String outTradeNo) {
        // 当前登录用户id
        Long userId = BaseContext.getCurrentId();

        // 根据订单号查询当前用户的订单
        OrdersEntity ordersEntity = ordersMapper.selectByNumberAndUserId(outTradeNo, userId);

        // 根据订单id更新订单的状态、支付方式、支付状态、结账时间
        ordersEntity
                .setStatus(OrderStatusConstant.NOT_ACCEPTED_ORDER)
                .setPayStatus(PayStatusConstant.PAID.shortValue())
                .setCheckoutTime(LocalDateTime.now())
                .updateById();

        //通过websocket向客户端浏览器推送消息 type orderId content
        Map map = new HashMap();
        map.put("type",1); // 1表示来单提醒 2表示客户催单
        map.put("orderId",ordersEntity.getId());
        map.put("content","订单号：" + outTradeNo);

        String json = JSON.toJSONString(map);
        webSocketServer.sendToAllClient(json);
    }

    @Override
    public OrdersVO searchOrderDetailByOrderId(Long id) {
        OrdersEntity ordersEntity = ordersMapper.selectById(id);
        OrdersVO ordersVO = new OrdersVO();

        BeanUtils.copyProperties(ordersEntity,ordersVO);

        List<OrderDetailEntity> orderDetailList = orderDetailMapper.selectListByOrderId(ordersEntity.getId());
        if (orderDetailList.size() < 0 || orderDetailList == null){
            throw new BusinessException("数据不存在");
        }
        ordersVO.setOrderDetailEntityList(orderDetailList);

        return ordersVO;
    }

    @Override
    public void userOfReminder(Long id) {
        OrdersEntity ordersEntity = ordersMapper.selectById(id);
        if (ObjectUtils.isEmpty(ordersEntity)){
            throw new BusinessException(MessageConstant.ORDER_NOT_FOUND);
        }

        Map map = new HashMap();
        map.put("type",2); //1表示来单提醒 2表示客户催单
        map.put("orderId",id);
        map.put("content","订单号：" + ordersEntity.getNumber());

        //通过websocket向客户端浏览器推送消息
        webSocketServer.sendToAllClient(JSON.toJSONString(map));
    }

    @Override
    public void userOfRepetition(Long id) {
        // 查询当前用户id
        Long userId = BaseContext.getCurrentId();

        // 根据订单id查询当前订单详情
        List<OrderDetailEntity> orderDetailList = orderDetailMapper.selectListByOrderId(id);

        // 将订单详情对象转换为购物车对象
        List<ShoppingCartEntity> shoppingCartList = orderDetailList.stream().map(source -> {
            ShoppingCartEntity shoppingCartEntity = new ShoppingCartEntity();

            // 将原订单详情里面的菜品信息重新复制到购物车对象中
            BeanUtils.copyProperties(source, shoppingCartEntity, "id");
            shoppingCartEntity.setUserId(userId);
            shoppingCartEntity.setCreateTime(LocalDateTime.now());

            return shoppingCartEntity;
        }).collect(Collectors.toList());

        // 将购物车对象批量添加到数据库
        shoppingCartMapper.insertBatch(shoppingCartList);
    }

    @Override
    public void userByCancel(Long id) throws Exception {
        OrdersEntity ordersEntity = ordersMapper.selectById(id);
        if (ObjectUtils.isEmpty(ordersEntity)){
            throw new BusinessException(MessageConstant.ORDER_NOT_FOUND);
        }

        if (ordersEntity.getStatus() > 2){
            throw new BusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }

        // 订单处于待接单状态下取消，需要进行退款
        if (ordersEntity.getStatus().equals(OrderStatusConstant.NOT_ACCEPTED_ORDER)) {
            //调用微信支付退款接口
            /*weChatPayUtil.refund(
                    ordersEntity.getNumber(), //商户订单号
                    ordersEntity.getNumber(), //商户退款单号
                    new BigDecimal(0.01),//退款金额，单位 元
                    new BigDecimal(0.01));//原订单金额*/

            //支付状态修改为 退款
            ordersEntity.setPayStatus(PayStatusConstant.REFUND.shortValue());
        }

        ordersEntity.setStatus(OrderStatusConstant.CANCEL)
                .setCancelReason("用户取消")
                .setCancelTime(LocalDateTime.now())
                .updateById();
    }
}

